using System.Collections.Generic;

namespace Yoozoo.Mars.Got
{
    public interface IMemoryPoolInterface
    {
        void Init();
        void Reset();
    }

    public class MemoryPool
    {
        private readonly int FILL_SIZE;
        private Stack<IMemoryPoolInterface> stack;
        public int BufferSize
        {
            get
            {
                if (stack == null)
                {
                    return 0;
                }
                return stack.Count;
            }
        }
        private float sumReqTimes;
        private float catchReqTimes;
        public float HitRate
        {
            get
            {
                if (sumReqTimes.Equals(0))
                {
                    return 0;
                }
                return catchReqTimes / sumReqTimes;
            }
        }

        public MemoryPool(int size)
        {
            FILL_SIZE = size;
            stack = new Stack<IMemoryPoolInterface>();
        }

        public void Fill<T>() where T : IMemoryPoolInterface
        {
            for (int i = 0; i < FILL_SIZE; i++)
            {
                var item = System.Activator.CreateInstance<T>();
                item.Init();
                stack.Push(item);
            }
        }

        public void Shrink()
        {
            if (stack.Count <= FILL_SIZE)
            {
                return;
            }
            var freeCount = stack.Count - FILL_SIZE;
            for (int i = 0; i < freeCount; i++)
            {
                stack.Pop();
            }
        }

        public void Clear()
        {
            stack.Clear();
        }

        public T GetItem<T>() where T : class, IMemoryPoolInterface
        {
            sumReqTimes++;
            if (stack.Count <= 0)
            {
                Fill<T>();
            }
            else
            {
                catchReqTimes++;
            }
            return stack.Pop() as T;
        }

        public void RecoverItem(IMemoryPoolInterface item)
        {
            item.Reset();
            stack.Push(item);
        }

        public void RecoverItems(IEnumerator<IMemoryPoolInterface> ie)
        {
            while (ie.MoveNext())
            {
                RecoverItem(ie.Current);
            }
        }
    }

    public class MemoryPoolMgr
    {
        private static MemoryPoolMgr instance;
        public static MemoryPoolMgr Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new MemoryPoolMgr();
                }
                return instance;
            }
        }

        public enum MEMORY_POOL_TYPE
        {
            HUDItem,
            SpriteVisitor,
            Max,
        }

        private bool isInited = false;
        private List<MemoryPool> pools = new List<MemoryPool>();

        private System.Text.StringBuilder strBuilder;

        public void Fill()
        {
            if (pools.Count == 0)
            {
                for (int i = 0; i < (int)MEMORY_POOL_TYPE.Max; i++)
                {
                    MemoryPool curPoolIns = null;
                    switch ((MEMORY_POOL_TYPE)i)
                    {
                        case MEMORY_POOL_TYPE.SpriteVisitor:
                            curPoolIns = new MemoryPool(1024);
                            curPoolIns.Fill<SpriteAnim.SpriteVisitor>();
                            break;
                    }
                    pools.Add(curPoolIns);
                }
            }

            isInited = true;
        }

        public void Shrink()
        {
            if (!isInited)
            {
                return;
            }
            if (pools.Count == 0)
            {
                return;
            }
            for (int i = 0; i < (int)MEMORY_POOL_TYPE.Max; i++)
            {
                var curPoolIns = pools[i];
                if (curPoolIns == null)
                {
                    continue;
                }
                curPoolIns.Shrink();
            }
        }

        public void Clear()
        {
            for (int i = 0; i < (int)MEMORY_POOL_TYPE.Max; i++)
            {
                var curPoolIns = pools[i];
                if (curPoolIns == null)
                {
                    continue;
                }
                curPoolIns.Clear();
            }
            pools.Clear();

            if (strBuilder != null)
            {
                strBuilder.Remove(0, strBuilder.Length);
                strBuilder = null;
            }
        }
        

        public SpriteAnim.SpriteVisitor GetSpriteVisitor()
        {
            var curPoolIns = pools[(int)MEMORY_POOL_TYPE.SpriteVisitor];
            return curPoolIns.GetItem<SpriteAnim.SpriteVisitor>();
        }

        public void RecoverItem(SpriteAnim.SpriteVisitor ins)
        {
            var curPoolIns = pools[(int)MEMORY_POOL_TYPE.SpriteVisitor];
            if (curPoolIns == null)
            {
                return;
            }
            curPoolIns.RecoverItem(ins);
        }
        
    }
}